package com.ruoyi.shoufang.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.shoufang.domain.*;
import com.ruoyi.shoufang.mapper.*;
import com.ruoyi.shoufang.service.TSfContractService;
import com.ruoyi.shoufang.utils.DateUtils;
import com.ruoyi.shoufang.utils.RegularCheckUtils;
import com.ruoyi.shoufang.utils.SendEmailUtils;
import com.ruoyi.system.api.model.LoginUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
* @author xuda
* @description 针对表【t_sf_contract】的数据库操作Service实现
* @createDate 2023-04-24 17:47:33
*/
@Service
public class TSfContractServiceImpl extends ServiceImpl<TSfContractMapper, TSfContract>
    implements TSfContractService{

    @Autowired
    private HouseInfoMapper houseInfoMapper;
    @Autowired
    private OwnerMapper ownerMapper;
    @Autowired
    private PremisesInfoMapper premisesInfoMapper;
    @Autowired
    private PaymentPlanMapper paymentPlanMapper;
    @Autowired
    private TSfContractMapper tSfContractMapper;
    @Autowired
    private TSfTerminationMapper tSfTerminationMapper;
    @Autowired
    private TSfFinalStatementDetailMapper tSfFinalStatementDetailMapper;
    @Value("${resources.path}")
    private String staticFilePath;

    /**
    * 收房合同查询
    * @return java.util.List<com.ruoyi.shoufang.domain.TSfContract>
    * @author xuda
    * @date 2023/4/24 18:06
    */
    @Override
    public List<TSfContract> searchContractList(TSfContract tSfContract) {
        return tSfContractMapper.searchContractList(tSfContract);
    }

    /**
    * 选择房产弹出List列表带分页
    * @return java.util.List<com.ruoyi.shoufang.domain.HouseInfo>
    * @author xuda
    * @date 2023/4/25 8:48
    */
    @Override
    public List<HouseInfo> searchHouseInfoList(HouseInfo houseInfo) {
        return tSfContractMapper.searchHouseInfoList(houseInfo);
    }


    @Transactional(rollbackFor=Exception.class)
    @Override
    public void saveSfContract(SaveSfContractForm saveSfContractForm) {
        //获取当前登录用户
        LoginUser loginUser = SecurityContextHolder.get(SecurityConstants.LOGIN_USER, LoginUser.class);
        //保存业主信息
        Owner owner = new Owner();
        //业主姓名
        owner.setOwnerName(saveSfContractForm.getOwnerName());
        //证件类型
        owner.setCertificateType(CertificateType.getName(saveSfContractForm.getCertificateType()));
        //收房合同编号
        // owner.setContractId(tSfContractMapper.selectNextSfht("SFHT"));
        //证件号码
        owner.setIdCard(saveSfContractForm.getOwnerIdCard());
        //手机号
        owner.setMobile(saveSfContractForm.getOwnerMobile());
        //联系地址
        owner.setAddress(saveSfContractForm.getCqAddress());
        //紧急联系电话
        owner.setUrgMobile(saveSfContractForm.getOwnerMobile());
        //银行卡号
        owner.setBankCard(saveSfContractForm.getBankCardNumber());
        //持卡人姓名
        owner.setBankUserName(saveSfContractForm.getOwnerName());
        //持卡人身份证
        owner.setBankUserIdCard(saveSfContractForm.getOwnerIdCard());
        //银行名称
        owner.setBankName(saveSfContractForm.getBankName());
        //开户支行
        owner.setBankOpen(saveSfContractForm.getBankOpen());
        //银行账户类型
        owner.setAccountType(saveSfContractForm.getAccountType().byteValue());
        //账户名称
        owner.setAccountName(saveSfContractForm.getAccountName());
        //联行行号
        owner.setBankBranchCodeLh(saveSfContractForm.getBankBranchCodeLh());
        //开户行所在省id
        owner.setBankAccountProvince(saveSfContractForm.getBankAccountProvince());
        //创建用户
        owner.setCreateUserid(loginUser.getUserid());
        //创建时间
        owner.setCreateTime(new Date());
        //删除标识
        owner.setDelFlg(false);
        //业主信息入库
        ownerMapper.insert(owner);
        //保存收房合同
        TSfContract sfContract = new TSfContract();
        BeanUtils.copyProperties(saveSfContractForm, sfContract);
        sfContract.setMonthRent(new BigDecimal(saveSfContractForm.getMonthRent()));
        sfContract.setDepositMoney(new BigDecimal(saveSfContractForm.getDepositMoney()));
        //收房合同编号
        sfContract.setSfContractNo(tSfContractMapper.selectNextSfht("SFHT"));
        //商户id    都写在一起，后期拆分
        sfContract.setBusinessId(houseInfoMapper.getBusinessIdByHouseId(saveSfContractForm.getHouseId()));
        //业主id
        sfContract.setOwnerId(owner.getId());
        //房产类型
        sfContract.setHouseLeaseType(saveSfContractForm.getLeaseTypeId());
        //合同录入人
        sfContract.setOperId(loginUser.getUserid());
        //收房人
        sfContract.setSfUserId(loginUser.getUserid());
        //收房人姓名
        sfContract.setSfUserName(loginUser.getUsername());
        //收房合同状态
        sfContract.setStatus(2);
        //收房合同续约状态
        sfContract.setXyStatus(0);
        //是否收房贷
        sfContract.setSfLoanFlg(0);
        //冻结状态
        sfContract.setFreezeStatus(0);
        //删除标识
        sfContract.setDelFlg(0);
        //创建用户ID
        sfContract.setCreateUserid(loginUser.getUserid());
        //创建时间
        sfContract.setCreateTime(new Date());
        //续约处理
        if (StringUtils.isNotEmpty(saveSfContractForm.getLastContractNo())) {
            //修改原合同
            tSfContractMapper.updateXyStatus(saveSfContractForm.getLastContractNo(),loginUser.getUserid());
        }
        //收房合同入库
        tSfContractMapper.insert(sfContract);
        //保存付款单
        List<CwPaymentPlan> cwPaymentPlanList = saveSfContractForm.getPayMentltems();
        for (CwPaymentPlan cwPaymentPlan : cwPaymentPlanList) {
            PaymentPlan paymentPlan = new PaymentPlan();
            BeanUtils.copyProperties(cwPaymentPlan,paymentPlan);
            //付款单号
            paymentPlan.setPayOrderNo(tSfContractMapper.selectNextSfht("FKJH"));
            //商户ID
            paymentPlan.setBusinessId(sfContract.getBusinessId());
            //合同ID
            paymentPlan.setContractId(sfContract.getId());
            //合同编号
            paymentPlan.setContractNo(sfContract.getSfContractNo());
            //合同类型  1：收房合同 2：出房合同
            paymentPlan.setContractType((byte)1);
            //解约协议ID
            paymentPlan.settTerminationId(null);
            //楼盘ID
            paymentPlan.setPremiseId(houseInfoMapper.getPremiseIdById(sfContract.getHouseId()));
            //楼盘名
            paymentPlan.setPremiseName(premisesInfoMapper.getPremiseNameById(paymentPlan.getPremiseId()));
            //业主ID
            paymentPlan.setOwnerId(owner.getId());
            //业主姓名
            paymentPlan.setOwnerName(owner.getOwnerName());
            //账单类型
            paymentPlan.setBillType((byte)3);
            //款项
            paymentPlan.setItemType((byte)80);
            //操作人
            paymentPlan.setOperationUser(loginUser.getUsername());
            //总期数
            paymentPlan.setTotalPayNumber(cwPaymentPlanList.get(0).getTotalPayNumber());
            //删除标识
            paymentPlan.setDelFlg(false);
            //创建用户ID
            paymentPlan.setCreateUserid(loginUser.getUserid());
            //创建时间
            paymentPlan.setCreateTime(new Date());
            // 预定付款日期
            paymentPlan.setPayableDate(cwPaymentPlan.getPaymentDaysBegin());
            //入库
            paymentPlanMapper.insert(paymentPlan);
        }
    }

    /**
    * 解约协议录入 {改房产状态,改合同状态,改付款单状态,添加解约协议,添加收退钱表,}
    * @return void
    * @author xuda
    * @date 2023/5/3 20:31
    */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void saveSfTermination(SaveSfContractForm saveSfContractForm) throws Exception {
        //获取当前登录用户
        LoginUser loginUser = SecurityContextHolder.get(SecurityConstants.LOGIN_USER, LoginUser.class);
        Date date = new Date();
        Long userid = loginUser.getUserid();
        // 改房产状态
        // houseInfoMapper.secureContract(date, userid, saveSfContractForm.getHouseId());
        // 改合同状态
        tSfContractMapper.secureContract(date, userid, saveSfContractForm.getSfContractNo());
        // 改付款单状态
        paymentPlanMapper.secureContract(date, userid, saveSfContractForm.getSfContractNo());
        TSfTermination sfTermination = new TSfTermination();
        // 解约协议编号
        sfTermination.setSfTerminationNo(tSfContractMapper.selectNextSfht("SFJY"));
        // 收房合同编号
        sfTermination.setSfContractNo(saveSfContractForm.getSfContractNo());
        // 小区名称
        sfTermination.setPremiseName(saveSfContractForm.getPremiseName());
        // 房产id
        sfTermination.setHouseId(saveSfContractForm.getHouseId());
        // 房产名字
        sfTermination.setHouseName(saveSfContractForm.getHouseName());
        // 产权地址
        sfTermination.setCqAddress(saveSfContractForm.getCqAddress());
        // 房展证书编号
        sfTermination.setHouseZsNo(saveSfContractForm.getHouseZsNo());
        // 业主姓名
        sfTermination.setOwnerName(saveSfContractForm.getOwnerName());
        // 业主手机号
        sfTermination.setOwnerMobile(saveSfContractForm.getOwnerMobile());
        // 签约人
        sfTermination.setSignUserName(saveSfContractForm.getSignUserName());
        // 签约人手机号
        sfTermination.setSignUserMobile(saveSfContractForm.getSignUserMobile());
        // 物业交割时间
        sfTermination.setWyjgDate(saveSfContractForm.getWyjgDate());
        // 解约类型
        sfTermination.setTerminationType(saveSfContractForm.getTerminationType());
        // 结算合计
        sfTermination.setFinalStatement(saveSfContractForm.getFinalStatement());
        // 解约日期
        sfTermination.setTerminationDate(date);
        // 审核日期
        sfTermination.setAuditDate(date);
        // 录入人id
        sfTermination.setInputUserId(userid);
        // 录入人姓名
        sfTermination.setInputUserName(loginUser.getUsername());
        // 录入日期
        sfTermination.setInputDate(date);
        // 备注
        sfTermination.setRemark(saveSfContractForm.getRemark());
        // 创建用户id
        sfTermination.setCreateUserid(userid);
        // 创建时间
        sfTermination.setCreateTime(date);
        // 解约协议录入
        tSfTerminationMapper.secureContract(sfTermination);
        // 应收应退表
        List<TSfFinalStatementDetail> statementList = saveSfContractForm.getStatementList();
        for (int i = 0; i < statementList.size(); i++) {
            TSfFinalStatementDetail tSfFinalStatementDetail = statementList.get(i);
            // 解约协议编号
            tSfFinalStatementDetail.setSfTerminationNo(sfTermination.getSfTerminationNo());
            // 收房合同编号
            tSfFinalStatementDetail.setSfContractNo(sfTermination.getSfContractNo());
            // 创建用户id
            tSfFinalStatementDetail.setCreateUserid(userid);
            // 创建时间
            tSfFinalStatementDetail.setCreateTime(date);
            tSfFinalStatementDetailMapper.secureContract(tSfFinalStatementDetail);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("signUserName",sfTermination.getSignUserName());
        data.put("leaseStartTime",saveSfContractForm.getLeaseStartTime());
        data.put("leaseEndTime",new Date());
        data.put("premiseName",sfTermination.getPremiseName());
        data.put("houseName",sfTermination.getHouseName());
        data.put("ownerName",sfTermination.getOwnerName());
        data.put("toemail","1174013501@qq.com");
        data.put("staticFilePath",staticFilePath);
        SendEmailUtils.sendEmail(data);
    }

    @Override
    public AjaxResult nextCfContract(SaveSfContractForm saveSfContractForm) {
        //业主证件号码校验
        String ownerIdCard = saveSfContractForm.getOwnerIdCard();
        if (StringUtils.isNotEmpty(ownerIdCard)) {
            if (saveSfContractForm.getCertificateType().equals(CertificateType.IDCARD) &&
                    !RegularCheckUtils.isIDCardNo(ownerIdCard))
                return AjaxResult.error("业主证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.passport) &&
                    !RegularCheckUtils.isPassport(ownerIdCard))
                return AjaxResult.error("业主证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.MTPS) &&
                    !RegularCheckUtils.isTBCard(ownerIdCard))
                return AjaxResult.error("业主证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.HKMACAOPASS) &&
                    !RegularCheckUtils.isHKMT(ownerIdCard))
                return AjaxResult.error("业主证件号码格式错误");
        }

        //判断是否为签约人,如果是,需要与业主信息符合
        if (saveSfContractForm.getSignWithOwner()==0?true:false) {
            if (!saveSfContractForm.getOwnerName().equals(saveSfContractForm.getSignUserName()))
                return AjaxResult.error("签约人信息与业主信息不匹配");
            if (!saveSfContractForm.getOwnerIdCard().equals(saveSfContractForm.getSignUserIdCard()))
                return AjaxResult.error("签约人信息与业主信息不匹配");
            if (!saveSfContractForm.getOwnerMobile().equals(saveSfContractForm.getSignUserMobile()))
                return AjaxResult.error("签约人信息与业主信息不匹配");
        }

        //签约人证件号校验
        String userIdCard = saveSfContractForm.getSignUserIdCard();
        if (StringUtils.isNotEmpty(userIdCard)) {
            if (saveSfContractForm.getCertificateType().equals(CertificateType.IDCARD) &&
                    !RegularCheckUtils.isIDCardNo(userIdCard))
                return AjaxResult.error("签约人证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.passport) &&
                    !RegularCheckUtils.isPassport(userIdCard))
                return AjaxResult.error("签约人证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.MTPS) &&
                    !RegularCheckUtils.isTBCard(userIdCard))
                return AjaxResult.error("签约人证件号码格式错误");
            if (saveSfContractForm.getCertificateType().equals(CertificateType.HKMACAOPASS) &&
                    !RegularCheckUtils.isHKMT(userIdCard))
                return AjaxResult.error("签约人证件号码格式错误");
        }

        //租约期限 校验
        //获得租约起始日期
        Date startDate = saveSfContractForm.getLeaseStartTime();
        //当前日期
        Date date = new Date();
        if (startDate.getTime() < date.getTime())
            return AjaxResult.error("租约起始时间不能小于当前时间");
        //获得租约结束时间
        Date endDate = saveSfContractForm.getLeaseEndTime();
        if (startDate.getTime() > endDate.getTime())
            return AjaxResult.error("租约起始时间不能大于结束时间");
        //租金校验
        String monthRent = saveSfContractForm.getMonthRent();
        if (Integer.parseInt(monthRent) < 0) {
            return AjaxResult.error("租金不能小于0");
        }
        //押金校验
        String depositMoney = saveSfContractForm.getDepositMoney();
        if (Integer.parseInt(depositMoney) < 0) {
            return AjaxResult.error("押金不能小于0");
        }
        //押期校验
        Integer depositType = saveSfContractForm.getDepositType();
        if (depositType < 0) {
            return AjaxResult.error("押期不能小于0");
        }
        //付期校验
        Integer paymentType = saveSfContractForm.getPaymentType();
        if (paymentType < 1) {
            return AjaxResult.error("付期不能小于1");
        }
        return AjaxResult.success();
    }

    @Override
    public R<Object> generatePayMentPlan(SaveSfContractForm saveSfContractForm) {
        // 付款单
        LinkedList<CwPaymentPlan> payMentltems = new LinkedList<CwPaymentPlan>();
        // 第几期
        int i = 1;

        //获得付几
        Integer depositType = saveSfContractForm.getPaymentType();

        // 有押金先加一个押金  押金和第一个周期都是第一期  后面累加
        if (StringUtils.isNotEmpty(saveSfContractForm.getDepositMoney())){
            CwPaymentPlan cwPaymentPlanDto = new CwPaymentPlan();
            //得到押金 （押金*押几）   HALF_UP舍入模式。这将导致结果四舍五入到最接近的值，并且如果有平局，那么将向远离零的方向舍入。
            cwPaymentPlanDto.setPaymentAmount(new BigDecimal(saveSfContractForm.getDepositMoney()).multiply(new BigDecimal(saveSfContractForm.getDepositType())).setScale(2, RoundingMode.HALF_UP));
            //获取房产租金周期的开始日期  （就是租约周期的开始时间）
            Date startDate = saveSfContractForm.getLeaseStartTime();
            cwPaymentPlanDto.setPaymentDaysBegin(startDate);
            //获取房产租金周期的结束日期 （周期开始时间 + "付几" 个月）减一天
            Date dateAfterMonths = DateUtils.getDateAfterMonths(startDate, saveSfContractForm.getPaymentType());
            Date endDate = DateUtils.getDateAfterDays(dateAfterMonths, -1);
            cwPaymentPlanDto.setPaymentDaysEnd(endDate);
            //税费
            cwPaymentPlanDto.setTax(BigDecimal.ZERO);
            //第几期
            cwPaymentPlanDto.setPayNumber(i);
            //付款状态 1:未收款 2：已收款 3：已中止
            cwPaymentPlanDto.setSkStatus(1);
            // 应该付款的日期  周期开始时间
            cwPaymentPlanDto.setPayableDate(startDate);
            // 月租金
            cwPaymentPlanDto.setRentalPrice(new BigDecimal(saveSfContractForm.getMonthRent()));
            // 款项（费用类型）,1:水费 2：电费，3：煤/燃气费，80：租金，81：押金，90：解约结算，99:其它
            cwPaymentPlanDto.setItemType(80);
            payMentltems.add(cwPaymentPlanDto);
        }

        for (;;){
            CwPaymentPlan cwPaymentPlanDto = new CwPaymentPlan();
            // 周期结束时间
            Date endDate = null;

            // 如果是第一期，那周期开始时间就是租约开始时间，如果不是第一期，那周期的开始时间是上一个周期的结束时间加一天
            if (i != 1 ){
                // 获取付款单集合中最后一个付款单，的结束时间
                Date paymentDaysEnd = payMentltems.getLast().getPaymentDaysEnd();
                // 给上一个周期的结束时间加一天，就是我这个周期的开始时间
                Date startDate = DateUtils.getDateAfterDays(paymentDaysEnd, 1);
                // 给付款单添加周期开始时间
                cwPaymentPlanDto.setPaymentDaysBegin(startDate);
                // 应该付款的日期  周期开始时间
                cwPaymentPlanDto.setPayableDate(startDate);

                // 获取周期结束时间   （周期开始时间 + "付几" 个月）减一天
                Date dateAfterMonths = DateUtils.getDateAfterMonths(startDate, saveSfContractForm.getPaymentType());
                endDate = DateUtils.getDateAfterDays(dateAfterMonths, -1);
                // 给付款单添加周期结束时间
                cwPaymentPlanDto.setPaymentDaysEnd(endDate);
            }else {
                // 获取房产租金周期的开始日期，因为是第一期，所以开始时间和租约开始时间相同就行
                Date startDate = saveSfContractForm.getLeaseStartTime();
                // 给付款单添加周期开始时间
                cwPaymentPlanDto.setPaymentDaysBegin(startDate);
                // 应该付款的日期  周期开始时间
                cwPaymentPlanDto.setPayableDate(startDate);

                // 获取房产租金周期的结束日期  （周期开始时间 + "付几" 个月）减一天
                Date dateAfterMonths = DateUtils.getDateAfterMonths(startDate, saveSfContractForm.getPaymentType());
                endDate = DateUtils.getDateAfterDays(dateAfterMonths, -1);
                // 给付款单添加周期结束时间
                cwPaymentPlanDto.setPaymentDaysEnd(endDate);
            }

            //税费
            cwPaymentPlanDto.setTax(BigDecimal.ZERO);
            //第几期
            cwPaymentPlanDto.setPayNumber(i);
            //付款状态 1:未收款 2：已收款 3：已中止
            cwPaymentPlanDto.setSkStatus(1);
            // 月租金
            cwPaymentPlanDto.setRentalPrice(new BigDecimal(saveSfContractForm.getMonthRent()));
            // 款项（费用类型）,1:水费 2：电费，3：煤/燃气费，80：租金，81：押金，90：解约结算，99:其它
            cwPaymentPlanDto.setItemType(80);
            //得到一期的金额   月租金*付几
            cwPaymentPlanDto.setPaymentAmount(new BigDecimal(saveSfContractForm.getMonthRent()).multiply(new BigDecimal(depositType)));

            // 如果周期的结束时间  超过  租约结束日期  那么这就是最后一期， 给最后一个周期的结束日期赋值（租约结束日期）
            // 金额要重新计算
            if (endDate.compareTo(saveSfContractForm.getLeaseEndTime()) > 0){
                cwPaymentPlanDto.setPaymentDaysEnd(saveSfContractForm.getLeaseEndTime());
                // 计算有几个整月月 * 月租金, 算剩下的 不足一个月的有几天  算日租金30天来算
                // 周期结束日期到开始日期有几个整月，周期开始日期加上（前面有几个整月就加几个），然后算结束日期到前面算出来的这个日期有多少天
                int[] diffBetweenTwoDate = DateUtils.getDiffBetweenTwoDate(cwPaymentPlanDto.getPaymentDaysBegin(), cwPaymentPlanDto.getPaymentDaysEnd());
                int diffMonths = diffBetweenTwoDate[1];
                int diffDays = diffBetweenTwoDate[2];
                BigDecimal monthRent = new BigDecimal(saveSfContractForm.getMonthRent()).multiply(new BigDecimal(diffMonths));
                BigDecimal dayRent = new BigDecimal(saveSfContractForm.getMonthRent()).multiply(new BigDecimal(diffDays).divide(new BigDecimal("30"), 2, RoundingMode.HALF_UP));
                cwPaymentPlanDto.setPaymentAmount(monthRent.add(dayRent));
            }
            payMentltems.add(cwPaymentPlanDto);

            // 如果周期的结束时间  超过或等于  租约结束日期  那么这就是最后一期  结束循环
            if (endDate.compareTo(saveSfContractForm.getLeaseEndTime()) >= 0){
                payMentltems.get(0).setTotalPayNumber(i);
                break;
            }

            // 周期数累加
            i++;
        }
        return R.ok(payMentltems);
    }

    @Override
    public void updateFlagById(TSfContract sfContract) {
        tSfContractMapper.updateFlagById(sfContract);
    }

}




